// Copyright (C) 2008 Taylor L. Riche <riche@cs.utexas.edu>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

/**
 * 
 */
package appcomp.entities;

import java.util.ArrayList;
import java.net.URI;

import core.CodeGenerator;
import core.Entity;
import utility.*;
import java.lang.Exception;


/**
 * @author riche
 *
 */
public class State extends Entity {
	
	private final String install;
	private final String get;
	private final String purge;
	private final FlowSig flowSig;
	private final ArrayList<String> dataList;
	private String init;
	private boolean isComp;
	
	/**
	 * @param install
	 * @param get
	 * @param purge
	 * @param dataList
	 */
	public State(final String install, final String get, final String purge, final FlowSig flowSig, final ArrayList<String> dataList, URI fileURI) {
		this.install = install;
		this.get = get;
		this.purge = purge;
		this.flowSig = flowSig;
		this.dataList = dataList;
		this.setFileURI(fileURI);
		this.init = null;
		this.isComp = false;
	}
	
	public State(String init, final String install, final String get, final String purge, final FlowSig flowSig, final ArrayList<String> dataList, URI fileURI) {
		this.install = install;
		this.get = get;
		this.purge = purge;
		this.flowSig = flowSig;
		this.dataList = dataList;
		this.setFileURI(fileURI);
		this.init = init;
		this.isComp = false;
	}
	
	public static State create(String install, String get, String purge, FlowSig fs, ArrayList<String> dataList, URI fileURI) {
		return new State(install, get, purge, fs, dataList, fileURI);
	}

	public static State create(String init, String install, String get, String purge, FlowSig fs, ArrayList<String> dataList, URI fileURI) {
		return new State(init, install, get, purge, fs, dataList, fileURI);
	}

	/**
	 * @return the dataList
	 */
	public ArrayList<String> getDataList() {
		return dataList;
	}

	/**
	 * @return the get
	 */
	public String getGet() {
		return get;
	}

	/**
	 * @return the install
	 */
	public String getInstall() {
		return install;
	}

	/**
	 * @return the purge
	 */
	public String getPurge() {
		return purge;
	}

	/**
	 * @return the flowSig
	 */
	public FlowSig getFlowSig() {
		return flowSig;
	}

	/* (non-Javadoc)
	 * @see appcomp.entities.Entity#generateCode()
	 */
	@Override
	public void generateCode(CodeGenerator cg) {
	    if(this.dataList != null) {
	        for(String d : this.dataList) {
	            this.getFile().println("\t" + d + ";");
	        }
	    }
		if (!isComp) {
            // TODO add flow signature information in these method arguments
            this.getFile().println();
            this.getFile().println("\tvoid " + this.install + "(void * data);");
            this.getFile().println("\tvoid * " + this.get + "();");
            this.getFile().println("\tvoid " + this.purge + "(void * data);");
            this.getFile().println("\tvoid " + this.init + "();");
        }
        if(this.getFlowSig() != null) {
			// add flow map	
			this.getFile().println();
			this.getFile().println("\tstd::vector<std::pair<lagniappe::ProcElement *, unsigned int> *> flowMap;");
		}

		
	}
	
	public void generateInit() throws Exception {
		if(init == null) {
			throw new Exception();
		}
		else {
			for(String d : this.dataList) {
				this.getFile().println("\t\t" + d + "." + this.init + "();");
			}
		}
	}


    /**
	 * @return the init
	 */
	public String getInit() {
		return init;
	}

    /**
     * @return the isComp
     */
    public boolean isComp() {
        return isComp;
    }

    /**
     * @param isComp the isComp to set
     */
    public void setComp(boolean isComp) {
        this.isComp = isComp;
    }

}
